﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HelloWin
{
    public partial class Form1 : Form
    {
        private const int W_SE_RESIZE = 17;
        private const int GWL_EXSTYLE = -20;
        private const int WS_EX_LAYERED = 0x80000;
        private const int WM_NCLBUTTONDOWN = 0xA1;
        private const int HTBORDER = 18;
        private const int HTBOTTOM = 15;
        private const int HTBOTTOMLEFT = 16;
        private const int HTBOTTOMRIGHT = 17;
        private const int HTCAPTION = 2;
        private const int HTLEFT = 10;
        private const int HTRIGHT = 11;
        private const int HTTOP = 12;
        private const int HTTOPLEFT = 13;
        private const int HTTOPRIGHT = 14;
        private const int BorderWidth = 5;
        private bool atBorder;
        private ResizeDirection _resizeDir = ResizeDirection.None;
        private int Aero = 0;
        public bool useScreen = true;
        public Point lastMouseDown;

        // for Aero 
        public struct MARGINS { 
            public int m_Left; public int m_Right; 
            public int m_Top; public int m_Bottom; }

        [DllImport("dwmapi.dll")]
        private static extern void DwmIsCompositionEnabled(ref int enabledptr);

        [DllImport("dwmapi.dll")]
        private static extern bool DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margin);

        [DllImport("user32.dll")]
        private static extern bool ReleaseCapture();

        [DllImport("user32.dll")]
        private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

        public Form1()
        {
            InitializeComponent();
            if (useScreen)
            {
                this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
                    ControlStyles.AllPaintingInWmPaint |
                    ControlStyles.UserPaint, true);
                this.UpdateStyles();
                this.DoubleBuffered = true;
            }
            if (Aero > 0){
                if (System.Environment.OSVersion.Version.Major >= 6)
                     DwmIsCompositionEnabled(ref Aero);    //检测Aero是否为打开
            }
            if (Aero > 0)
            {
                MARGINS mg = new MARGINS{ m_Bottom = -1, m_Right = -1,
                             m_Left = -1, m_Top = -1};
                DwmExtendFrameIntoClientArea(this.Handle, ref mg); 
            }
        }
        
        private Bitmap bmpFromScreen()
        {
            Bitmap bgBmp = new Bitmap(this.Width, this.Height);
            Graphics g = Graphics.FromImage(bgBmp);
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
            g.CopyFromScreen(this.Left, this.Top, 0, 0, new Size(this.Width, this.Height));
            g.Dispose();
            return bgBmp;
        }

        private Bitmap bmpFromColor(Color color)
        {
            Bitmap bgBmp = new Bitmap(this.Width, this.Height);
            Graphics g = Graphics.FromImage(bgBmp);
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
            g.Clear(color);
            g.Dispose();
            return bgBmp;
        }

        public static Bitmap Mosaic(Bitmap img, int size)
        {
          for (int h = 0; h < img.Height; h += size)
          {
            for (int w = 0; w < img.Width; w += size)
            {
                int avgR = 0, avgG = 0, avgB = 0;
                int count = 0;
                for (int x = w; (x < w + size && x < img.Width); x++)
                {
                    for (int y = h; (y < h + size && y < img.Height); y++)
                    {
                        Color pix = img.GetPixel(x, y);
                        avgR += pix.R;
                        avgG += pix.G;
                        avgB += pix.B;
                        count++;
                    }
                }
                avgR = avgR / count;
                avgG = avgG / count;
                avgB = avgB / count;
                for (int x = w; (x < w + size && x < img.Width); x++)
                {
                    for (int y = h; (y < h + size && y < img.Height); y++)
                    {
                        Color newColor = Color.FromArgb(avgR, avgG, avgB);
                        img.SetPixel(x, y, newColor);
                    }
                }
            }
          }
          return img;
        }

        public enum ResizeDirection 
        { 
            None = 0, Left = 1, TopLeft = 2, Top = 3, TopRight = 4, 
            Right = 5, BottomRight = 6, Bottom = 7, BottomLeft = 8
        }

        public ResizeDirection resizeDir
        {
            get { return _resizeDir; }
            set
            {
                _resizeDir = value;

                switch(value)
                {
                    case ResizeDirection.Left:
                        this.Cursor = Cursors.SizeWE;
                        break;
                    case ResizeDirection.Right:
                        this.Cursor = Cursors.SizeWE;
                        break;
                    case ResizeDirection.Top:
                        this.Cursor = Cursors.SizeNS;
                        break;
                    case ResizeDirection.Bottom:
                        this.Cursor = Cursors.SizeNS;
                        break;
                    case ResizeDirection.BottomLeft:
                        this.Cursor = Cursors.SizeNESW;
                        break;
                    case ResizeDirection.TopRight:
                        this.Cursor = Cursors.SizeNESW;
                        break;
                    case ResizeDirection.BottomRight:
                        this.Cursor = Cursors.SizeNWSE;
                        break;
                    case ResizeDirection.TopLeft:
                        this.Cursor = Cursors.SizeNWSE;
                        break;
                    default:
                        this.Cursor = Cursors.Default;
                        break;
                }
            }
        }


        // #Region " Moving & Resizing methods "

        private void MoveForm()
        {
            ReleaseCapture();
            SendMessage(this.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
        }

        private void ResizeForm(ResizeDirection direction)
        {
            int dir = -1;
            switch(direction)
            {
                case ResizeDirection.Left:
                    dir = HTLEFT;
                    break;
                case ResizeDirection.TopLeft:
                    dir = HTTOPLEFT;
                    break;
                case ResizeDirection.Top:
                    dir = HTTOP;
                    break;
                case ResizeDirection.TopRight:
                    dir = HTTOPRIGHT;
                    break;
                case ResizeDirection.Right:
                    dir = HTRIGHT;
                    break;
                case ResizeDirection.BottomRight:
                    dir = HTBOTTOMRIGHT;
                    break;
                case ResizeDirection.Bottom:
                    dir = HTBOTTOM;
                    break;
                case ResizeDirection.BottomLeft:
                    dir = HTBOTTOMLEFT;
                    break;
            }

            if (dir != -1)
            {
                ReleaseCapture();
                SendMessage(this.Handle, WM_NCLBUTTONDOWN, dir, 0);
            }

        }
        // #End Region

        //
        // ALL USER INPUT
        //
        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            // Calculate which direction to resize based on mouse position
            if (e.Location.X < BorderWidth & e.Location.Y < BorderWidth)
            {
                resizeDir = ResizeDirection.TopLeft;
                atBorder = true;
            }

            else if (e.Location.X < BorderWidth & e.Location.Y > this.Height - BorderWidth )
            {
                resizeDir = ResizeDirection.BottomLeft;
                atBorder = true;
            }
            else if (e.Location.X > this.Width - BorderWidth & e.Location.Y > this.Height - BorderWidth)
            {
                resizeDir = ResizeDirection.BottomRight;
                atBorder = true;
            }
            else if (e.Location.X > this.Width - BorderWidth & e.Location.Y < BorderWidth)
            {
                resizeDir = ResizeDirection.TopRight;
                atBorder = true;
            }
            else if (e.Location.X < BorderWidth)
            {
                resizeDir = ResizeDirection.Left;
                atBorder = true;
            }
            else if ( e.Location.X > this.Width - BorderWidth)
            {
                resizeDir = ResizeDirection.Right;
                atBorder = true;
            }
            else if (e.Location.Y < BorderWidth)
            {
                resizeDir = ResizeDirection.Top;
                atBorder = true;
            }
            else if ( e.Location.Y > this.Height - BorderWidth)
            {
                resizeDir = ResizeDirection.Bottom;
                atBorder = true;
            }
            else{
                resizeDir = ResizeDirection.None;
                atBorder = false;
            }
        }

        private void Form1_MouseDown(object sender,MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (e.Location == lastMouseDown)
                {
                    show_hide();
                    lastMouseDown = new Point(0,0);
                }else
                {
                    lastMouseDown = e.Location;
                }


                if (atBorder)
                    ResizeForm(resizeDir);
                else{
                    MoveForm();
                }
            }

        }

        private void Button1_MouseDown( object sender, EventArgs e)
        {
            Application.Exit();
            // Environment.Exit(0);
        }

        private void show_hide()
        {
            Button1.Visible =  ! Button1.Visible;
            Button2.Visible =  ! Button2.Visible;
            Button3.Visible =  ! Button3.Visible;
            HScrollBar1.Visible = ! HScrollBar1.Visible;
        }

        private void HScrollBar1_ValueChanged(object sender, EventArgs e)
        {
            this.Opacity = (double)this.HScrollBar1.Value / 1000;
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            Button1.Left = this.Width - Button1.Width;
            Button2.Left = this.Width - Button1.Width - Button2.Width;
            HScrollBar1.Top = this.Height - HScrollBar1.Height;
            HScrollBar1.Width = this.Width;
        }
        
        private void Timer1_Tick(object sender, EventArgs e)
        {
            if (useScreen){
                this.BackgroundImage =  Mosaic(bmpFromScreen(), 10);
                this.Refresh();
            }
            this.TopMost = true;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            HScrollBar1.Visible = false;
            Button1.Visible = false;
            Button2.Visible = false;
            Button3.Visible = false;

            Timer1.Enabled = true;

            if (useScreen){
                this.BackgroundImage = Mosaic(bmpFromScreen(), 10);
            }else{
                    this.BackgroundImage = bmpFromColor(Color.Black);
            }
        }

        private void Form1_LostFocus(object sender, EventArgs e)
        {
            HScrollBar1.Visible = false;
            Button1.Visible = false;
            Button2.Visible = false;
            Button3.Visible = false;
        }

        private void Button3_MouseDown(object sender, EventArgs e)
        {
            useScreen = !useScreen;
            if (useScreen){
                this.BackgroundImage = Mosaic(bmpFromScreen(), 10);
                this.Button3.Text = "! Masaic";
            }else{
                    this.Timer1.Enabled = false;
                    if (this.ColorDialog1.ShowDialog() == DialogResult.OK){
                        this.Button3.Text = "! Pure";
                        this.BackgroundImage = bmpFromColor(this.ColorDialog1.Color);
                    }
                    else{
                        useScreen = !useScreen;
                    }
                    this.Timer1.Enabled = true;

            }

        }

        private void Button2_MouseDown(object sender, EventArgs e)
        {
            string helpstr = 
        @"
        SubtitleCover v0.0.1
        Author: Shawn            
        **************************************************************
        *** Grag to move the SubtitleCover
        *** Put your mouse at the edge to resize
        *** Double Click to show all controls
        *** Scroll to change the transparency
        *** Click the left top Button to change mode             
        *** Please don't resize it to be too large
        **************************************************************
        All Right Reserved ";


            Timer1.Enabled = false;
            MessageBox.Show(helpstr,"Help");
            Timer1.Enabled = true;
        }

    }
}
